package com.dingreading.cloud.mall.service.impl;

import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.AccountUtil;
import com.dingreading.cloud.common.util.EnumOperationType;
import com.dingreading.cloud.common.util.PageDto;
import com.dingreading.cloud.common.util.PageUtil;
import com.dingreading.cloud.mall.dto.*;
import com.dingreading.cloud.mall.entity.CouponStaff;
import com.dingreading.cloud.mall.entity.Goods;
import com.dingreading.cloud.mall.entity.GoodsImg;
import com.dingreading.cloud.mall.entity.Stores;
import com.dingreading.cloud.mall.entity.table.GoodsTableDef;
import com.dingreading.cloud.mall.mapper.GoodsMapper;
import com.dingreading.cloud.mall.service.*;
import com.dingreading.cloud.mall.util.GoodsV3Util;
import com.dingreading.cloud.mall.util.OrderFormV3Util;
import com.dingreading.cloud.mall.util.ShopCartUtilV2;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 服务层实现。
 *
 * @author Administrator
 * @since 2023-11-22
 */
@Service
public class GoodsServiceImpl extends BaseServiceImpl<GoodsMapper, Goods, GoodsTableDef> implements GoodsService {

    @Override
    protected GoodsTableDef getTable() {
        return GoodsTableDef.goods;
    }

    @Resource
    protected GoodsTypeService goodsTypeService;
    @Resource
    protected GoodsImgService goodsImgService;
    @Resource
    protected GoodsTypeComboService goodsTypeComboService;
    @Resource
    protected StoreGoodsDiscountService storeGoodsDiscountService;
    @Resource
    protected StoresService storesService;
    @Resource
    protected WhStockInService stockInService;
    @Resource
    protected ShopCartService shopCartService;
    @Resource
    protected CouponStaffService couponStaffService;


    private GoodsDto getDataById(Long id) {
        QueryWrapper wrapper = QueryWrapper.create()
                .where(table.id.eq(id));
        return getMapper().selectOneWithRelationsByQueryAs(wrapper, GoodsDto.class);
    }

    @Override
    public R<Object> get(String storeUid, String staffUid, Long id) {
        Stores stores = storesService.getByUid(storeUid);
        if (stores == null)
            return R.fail("门店不存在");

        Integer operationType = stores.getOperationType();
        String cooperationType = stores.getCooperationType();
        String storesSubjectType = stores.getSubjectType();
        if (StringUtils.isBlank(storesSubjectType))
            return R.fail("门店未分配科目，请联系运营人员");

        List<Long> subjectIdList = Arrays.stream(StringUtils.split(stores.getSubjectType(), ","))
                .map(Long::valueOf).collect(Collectors.toList());

        List<Integer> cooperationTypeList = new ArrayList<>();
        if (StringUtils.isNotBlank(cooperationType)) {
            cooperationTypeList = Arrays.stream(StringUtils.split(cooperationType, ","))
                    .map(Integer::valueOf).collect(Collectors.toList());
        }

        GoodsDto goodsDto = getDataById(id);
        if (goodsDto == null)
            return R.fail("获取失败");

        // 商品封面图
        List<GoodsImg> imgList = goodsImgService.getByGoodsId(id);
        goodsDto.setImgList(imgList);

        // 商品规格
        List<GoodsTypeInfoDto> typeList = goodsTypeService.typeInfoListByGoodsIdAndEnabled(
                id, operationType, cooperationTypeList, subjectIdList
        );

        double maxGoodsTypePrice = 0;
        if (CollectionUtils.isNotEmpty(typeList)) {
            Set<Long> typeIds = new HashSet<>();
            Set<Long> comboTypeIds = new HashSet<>();

            for (GoodsTypeInfoDto dto : typeList) {
                if (dto.getComboType().equals(0))
                    typeIds.add(dto.getId());
                else
                    comboTypeIds.add(dto.getId());
            }

            // 查询组合商品的子商品信息
            Map<Long, List<GoodsTypeComboDto>> comboMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(comboTypeIds)) {
                List<GoodsTypeComboDto> goodsTypeComboList = goodsTypeComboService.dtoListByMainGoodsTypeIds(new ArrayList<>(comboTypeIds));
                if (CollectionUtils.isNotEmpty(goodsTypeComboList)) {
                    comboMap = goodsTypeComboList.stream().collect(Collectors.groupingBy(GoodsTypeComboDto::getMainGoodsTypeId, LinkedHashMap::new, Collectors.toList()));

                    List<Long> childGoodsTypeIds = goodsTypeComboList.stream().map(GoodsTypeComboDto::getGoodsTypeId).collect(Collectors.toList());
                    typeIds.addAll(childGoodsTypeIds);
                }
            }

            // 轻量门店的商品折扣规则
            Double storeGoodsDiscountRate = storeGoodsDiscountService.getDiscountRate(storeUid);
            // 获取用户可用的商品抵扣券的商品id集合
            Set<Long> couponGoodsIdList = getCouponGoodsIdList(storeUid, staffUid);

            List<Long> goodsTypeIds = new ArrayList<>(typeIds);
            // 商品规格的库存数量
            Map<Long, Integer> stockNumMap = stockInService.getStockNumMap(goodsTypeIds);
            // 商品规格的待发货数量
            Map<Long, Integer> waitSendNumMap = shopCartService.getWaitSendNum(goodsTypeIds);

            for (GoodsTypeInfoDto dto : typeList) {
                Long typeId = dto.getId();
                if (dto.getComboType().equals(0)) {
                    // 正常商品
                    int stockNum = OrderFormV3Util.getGoodsTypeNum(stockNumMap.get(typeId), waitSendNumMap.get(typeId));
                    dto.setStockNum(stockNum);
                } else {
                    // 组合商品
                    List<GoodsTypeComboDto> comboDtoList = comboMap.get(dto.getId());
                    // 获取组合商品的最低可售数量和总重量
                    ComboGoodsTypeDto comboGoodsTypeDto = GoodsV3Util.getComboGoodsTypeDto(comboDtoList, stockNumMap, waitSendNumMap);
                    dto.setStockNum(comboGoodsTypeDto.getSaleNum());
                    dto.setWeight(comboGoodsTypeDto.getWeight());

                    dto.setComboList(comboDtoList);
                }

                // 计算购物车商品的单价（学科折扣）
                ShopCartPriceDto priceDto = ShopCartUtilV2.getDiscountRateUnitPrice(
                        dto.getPrice(), dto.getDiscountStatus(), storeGoodsDiscountRate
                );
                dto.setPrice(priceDto.getUnitPrice());
                dto.setOriginalPrice(priceDto.getOriginalUnitPrice());
                if (maxGoodsTypePrice < priceDto.getUnitPrice()) {
                    maxGoodsTypePrice = priceDto.getUnitPrice();
                }
            }
        }
        // 找到最大的商品规格单价
        goodsDto.setPrice(maxGoodsTypePrice);
        goodsDto.setTypeList(typeList);

        return R.ok(goodsDto);
    }


    @Override
    public R<Object> pageListV2(PageUtil pageUtil, String storeUid, String staffUid, String name, Long categoryId) {
        Stores stores = storesService.getByUid(storeUid);
        if (stores == null)
            return R.fail("门店不存在");

        Integer operationType = stores.getOperationType();
        String cooperationType = stores.getCooperationType();
        String storesSubjectType = stores.getSubjectType();
        if (StringUtils.isBlank(storesSubjectType))
            return R.fail("门店未分配科目，请联系运营人员");

        // 获取运营类型
        List<Integer> cooperationTypeList = new ArrayList<>();
        if (StringUtils.isNotBlank(cooperationType)) {
            cooperationTypeList = Arrays.stream(StringUtils.split(cooperationType, ","))
                    .map(Integer::valueOf).collect(Collectors.toList());
        }

        // 获取门店的服务
        List<Long> subjectIdList = new ArrayList<>();
        if (StringUtils.isNotBlank(stores.getSubjectType())) {
            subjectIdList = Arrays.stream(StringUtils.split(stores.getSubjectType(), ","))
                    .map(Long::valueOf).collect(Collectors.toList());
        }

        // 商品分页
        PageDto<GoodsDto> pageDto = storePageListXml(
                pageUtil, name, categoryId, cooperationTypeList, operationType, subjectIdList
        );

        List<GoodsDto> list = pageDto.getList();
        if (CollectionUtils.isNotEmpty(list)) {
            // 门店的商品折扣规则
            Double storeGoodsDiscountRate = storeGoodsDiscountService.getDiscountRate(storeUid);

            // 获取用户可用的商品抵扣券的商品id集合
            Set<Long> couponGoodsIdList = getCouponGoodsIdList(storeUid, staffUid);

            // 商品规格查询
            List<Long> goodsIdList = list.stream().map(GoodsDto::getId).collect(Collectors.toList());
            List<GoodsTypeInfoDto> goodsTypeList = goodsTypeService.typeInfoList(goodsIdList, operationType, cooperationTypeList, subjectIdList);
            if (CollectionUtils.isNotEmpty(goodsTypeList)) {
                Map<Long, List<GoodsTypeInfoDto>> goodsTypeMap = null;
                if (CollectionUtils.isNotEmpty(goodsTypeList)) {
                    goodsTypeMap = goodsTypeList.stream().collect(Collectors.groupingBy(GoodsTypeInfoDto::getGoodsId));
                }

                for (GoodsDto goods : list) {
                    List<GoodsTypeInfoDto> goodsTypes = goodsTypeMap.get(goods.getId());
                    if (CollectionUtils.isNotEmpty(goodsTypes)) {
                        // 重新设置商品的价格
                        double maxUnitPrice = 0;
                        for (GoodsTypeInfoDto goodsType : goodsTypes) {
                            ShopCartPriceDto priceDto = ShopCartUtilV2.getDiscountRateUnitPrice(
                                    goodsType.getPrice(), goodsType.getDiscountStatus(), storeGoodsDiscountRate
                            );
                            double unitPrice = priceDto.getUnitPrice();
                            if (maxUnitPrice < unitPrice) {
                                maxUnitPrice = unitPrice;
                            }
                        }
                        goods.setPrice(maxUnitPrice);
                    }
                }
            }
        }
        return R.ok(pageDto);
    }


    /**
     * 获取用户可用的商品抵扣券的商品id集合
     */
    @Override
    public Set<Long> getCouponGoodsIdList(String storeUid, String staffUid) {
        // 用户可用的商品抵扣券
        List<CouponStaff> couponStaffGoodsList = couponStaffService.staffUseGoodsCouponList(storeUid, staffUid);
        if (CollectionUtils.isEmpty(couponStaffGoodsList)) {
            return null;
        }

        Set<Long> couponGoodsIdList = new HashSet<>();
        Set<String> categoryIdList = new HashSet<>();
        for (CouponStaff couponStaff : couponStaffGoodsList) {
            // 商品id
            String goodsIds = couponStaff.getGoodsIds();
            if (StringUtils.isNotBlank(goodsIds)) {
                List<Long> goodsIdList = Arrays.stream(StringUtils.split(goodsIds, ","))
                        .map(Long::valueOf).distinct().collect(Collectors.toList());
                couponGoodsIdList.addAll(goodsIdList);
            }
            // 商品分类id
            String goodsCategoryIds = couponStaff.getGoodsCategoryIds();
            if (StringUtils.isNotBlank(goodsCategoryIds)) {
                List<String> categoryIds = Arrays.stream(StringUtils.split(goodsCategoryIds, ","))
                        .distinct().collect(Collectors.toList());
                categoryIdList.addAll(categoryIds);
            }
        }
        // 通过商品分类id查询商品id集合
        if (CollectionUtils.isNotEmpty(categoryIdList)) {
            List<Long> goodsIdList = idListByCategoryIdIn(categoryIdList);
            if (CollectionUtils.isNotEmpty(goodsIdList))
                couponGoodsIdList.addAll(goodsIdList);
        }
        return couponGoodsIdList;

    }

    /**
     * 通过商品分类id查询商品id集合
     */
    @Override
    public List<Long> idListByCategoryIdIn(Set<String> categoryIdList) {
        String categoryIdsJoin = categoryIdList.stream().collect(Collectors.joining("|"));
        String sql = "category_ids REGEXP '(^|,)(" + categoryIdsJoin + ")(,|$)'";

        QueryWrapper wrapper = QueryWrapper.create()
                .select(table.id)
                .from(table)
                .where(sql);
        return getMapper().selectObjectListByQueryAs(wrapper, Long.class);
    }

    /**
     * 商品分页
     */
    private PageDto<GoodsDto> storePageListXml(
            PageUtil pageUtil, String name, Long categoryId, List<Integer> cooperationType,
            Integer operationType, List<Long> subjectIdList
    ) {
        //设置其他参数
        Map<String, Object> otherParams = new HashMap<>();
        otherParams.put("name", name);
        otherParams.put("categoryId", categoryId);
        otherParams.put("cooperationTypeSql", AccountUtil.getCooperationTypeSql2(cooperationType));
        otherParams.put("operationTypeSql", AccountUtil.getOperationTypeSql2(operationType));
        boolean easyProductJoinType = operationType.equals(EnumOperationType.EASY_PRODUCT_JOIN.getType());
        otherParams.put("easyProductJoinType", easyProductJoinType);
        String subjectTypeSql = "";
        if (CollectionUtils.isNotEmpty(subjectIdList)) {
            String subjectIdSql = subjectIdList.stream().map(String::valueOf).collect(Collectors.joining("|"));
            subjectTypeSql = "(^|,)(" + subjectIdSql + ")(,|$)";
        }
        otherParams.put("subjectTypeSql", subjectTypeSql);

        Page<GoodsDto> page = getMapper().xmlPaginate("storePageListXml", Page.of(pageUtil.getPage(), pageUtil.getRows()), otherParams);

        long totalRow = page.getTotalRow();
        List<GoodsDto> list = page.getRecords();

        // 结果
        PageDto<GoodsDto> dto = new PageDto<>();
        dto.setList(list);
        dto.setTotal(totalRow);
        return dto;
    }

}
